import threading
import multiprocessing

import psutil

from DataDistribution.distribution import Distributor
from DataMonitoring.Monitor import FileMonitor
from DataProcessing.FileProcessing import FileControl
from DataProcessing.DatabaseProcessing import DataControl
from LogFIle.ImosLog import LogFileControl
from Log.addLog import Logs
from Extend.FileMethod import FileExtend
from ImosChange.ImosDataChange import IMOSChangeControl
import os
import sys
from LogFIle.LogCollation import LogCollation
import re
from Extend.NoSql import Heart


class ServiceMainControl:
    """
    保持一种方式，第一个参数为本地的，第二个参数是远程的:
    分发器的类 Distributor 初始化需要传入一个远端服务器列表, 和本地的文件所在路径
    [{'Server': "172.16.200.147", 'Weight': 5, 'DistributePath': "testdir"}]
    日志监控类 FileMonitor 这个类只需要传入一个变量，传入的是远端服务器列表
     [{'Server': "172.16.200.21", 'LogPath': "LogFiles"}]
    数据库汇总类 DataControl 这个类需要传入两个变量，一个本地服务器数据库配置，一个远程服务器配置列表
        [{'Server': '172.16.200.21', 'User': 'sa', 'Password': '2020', 'DataBase': 'LWJ'}]
    文件汇总类 FileControl 这个类需要传入两个变量，一个本地服务器文件保存位置，一个远程服务器配置列表
    [{'Server': '172.16.200.147', 'FilePath': ['Imoder','\product\ROVER','\product\CNC']}]
    生成本地Log的类，只需要传入一个本地log所在路径即可
    'D:////LogFile'
    存储本地数据类 Logs,需要传入一个本地数据库的连接信息
    {'Server': '172.16.200.21', 'User': 'sa', 'Password': '2020', 'DataBase': 'LWJ'}

    """
    # config_name = 'D:\\LSDataDistribution\\config.json'
    config_name = 'config.json'
    __limit = 0

    def __init__(self):
        if self.__limit > 0:
            raise SystemError("此类仅可以创建一个实例对象")

        self.local_config, self.target_config = self.setConfig()
        self.ddb = Distributor
        self.mon = FileMonitor
        self.db = DataControl
        self.fi = FileControl
        self.lf = LogFileControl
        self.log = Logs
        self.imos = IMOSChangeControl
        self.definitionServices()
        self.services_name = ['分发服务', '日志监控服务', '数据库抓取服务', '文件抓取服务', '日志生成服务', '日志记录服务', "IMOS更新同步"]
        self.services = [self.ddb, self.mon, self.db, self.fi, self.lf, self.log, self.imos]
        self.process = [x for x in range(len(self.services))]
        self.__limit += 1

    def setConfig(self):
        config = FileExtend.readJsonFile(ServiceMainControl.config_name)
        return config['Local'], config['Target']

    def start(self):
        while True:
            self.showMenu()
            u_input = input("请输入需要查询的指令:")
            print("\n\n")
            if not u_input.isnumeric() or len(u_input) > 3 or len(u_input) < 1:
                print("别瞎输，只能是数字")
                continue
            if u_input == '1':
                self.showAllServer()
            elif u_input == '4':
                self.startAllServer()
            elif u_input == '5':
                self.stopAllServer()
            elif u_input == '6':
                self.collation_log()
            elif u_input == '7':
                self.stopAllServer()
                exit()
            elif u_input.startswith('2'):
                if len(u_input) == 1:
                    print("必须带上启动的服务id号")
                else:
                    self.startSever(int(u_input[1]))
            elif u_input.startswith('3'):
                if len(u_input) == 1:
                    print("必须带上停止的服务id号")
                else:
                    self.stopSever(int(u_input[1]))
            else:
                print("你输的有问题啊")
            print("\n\n")

    def definitionServices(self):
        self.ddb = Distributor(self.local_config['DistributePath'],
                               [target['Distribution'] for target in self.target_config if
                                target['Distribution']])
        self.mon = FileMonitor([target['Monitor'] for target in self.target_config if
                                target['Monitor']])
        self.db = DataControl(self.local_config['DataProcessing'],
                              [target['DataProcessing'] for target in self.target_config if
                               target['DataProcessing']])
        self.fi = FileControl(self.local_config['DataProcessing'],
                              [target['DataProcessing'] for target in self.target_config if
                               target['DataProcessing']])
        self.lf = LogFileControl(self.local_config["LogPath"])
        self.log = Logs(self.local_config["LogServer"])
        self.imos = IMOSChangeControl(self.local_config["IMOSMainServer"],
                                      [target['IMOSMainServer'] for target in self.target_config if
                                       target['IMOSMainServer']])

    def __del__(self):
        self.__limit -= 1

    def showMenu(self):
        print("=" * 20 + "*" * 60 + "=" * 20)
        print("欢迎使用分发系统！")
        print("1.查询服务状态")
        print("2.启动服务(加上服务的id号)")
        print("3.停止服务(加上服务的id号)")
        print("4.启动所有服务")
        print("5.停止所有服务")
        print("6.整理日志")
        print("7.退出系统")
        print("=" * 20 + "*" * 60 + "=" * 20)

    def showAllServer(self):
        loop = 0
        print("-" * 100)
        for x, y, n in zip(self.process, self.services_name, self.services):
            if type(x) is not int and x.is_alive():
                stat = "正在运行"
            else:
                stat = "已经停止"
                Heart.setMeStat(n.__class__.__name__, False)
            print("id:{}\t{}{}".format(loop, y, stat))
            loop += 1
        else:
            print("-" * 100)

    def allServerStatus(self):
        loop = 0
        stops = []
        for proc, service in zip(self.process, self.services):
            try:
                pid = Heart.getPid(service.__class__.__name__)
                if type(proc) is not int and proc.is_alive() and psutil.pid_exists(pid):
                    pass
                else:
                    raise SystemError
            except Exception as err:
                print(err)
                stops.append(loop)
                Heart.setMeStat(service.__class__.__name__, False)
            finally:
                loop += 1
        return stops

    def startSever(self, index):
        if index > len(self.services):
            print("当前服务id不存在")
            return
        pid = Heart.getPid(self.services[index].__class__.__name__)
        print(pid)
        if type(self.process[index]) is int or self.process[index].is_alive() is False or not psutil.pid_exists(pid):
            Heart.setMeHeart(self.services[index].__class__.__name__, True)
            # proc = multiprocessing.Process(target=self.services[index].start, daemon=True)
            proc = threading.Thread(target=self.services[index].start, daemon=True)
            proc.start()
            self.process[index] = proc
            # self.services[index].start()
        print("{}已经运行".format(self.services_name[index]))

    def stopSever(self, index):
        if index > len(self.services):
            print("当前服务id不存在")
            return
        if type(self.process[index]) is not int:
            proc = self.process[index]
            # self.services[index].stop()
            Heart.setMeHeart(self.services[index].__class__.__name__, False)
            proc.join()
        print("{}已经停止".format(self.services_name[index]))

    def startAllServer(self):
        for index in range(len(self.services)):
            self.startSever(index)

    def stopAllServer(self):
        for index in range(len(self.services)):
            self.stopSever(index)

    def collation_log(self):
        print()
        print("-" * 100)
        print("请输入需要整理日志的时间，如:2020-06-01\n也可以输入当前天数向前多少天,例："
              "\n今天:0\t昨天:1\t前天2\n返回上级菜单请输入M")
        print("-" * 100)
        print()
        u_input = input("请输入：")
        try:
            if u_input.lower() == "m":
                return
            elif u_input.isnumeric():
                LogCollation.collationLog(Heart.getMeHeart(self.lf.__class__.__name__), subtraction=int(u_input))
            elif re.search(r"\d{4}-\d{2}-\d{2}", u_input):
                LogCollation.collationLog(Heart.getMeHeart(self.lf.__class__.__name__), collation_date=u_input)
            else:
                raise ValueError("你输入的不正确，请重新输入!")
        except Exception as err:
            if type(err.args[0]) is int:
                error = err.args[1]
            else:
                error = err.args[0]
            print("\n\n{}".format(error))
            return


if __name__ == '__main__':
    services = ServiceMainControl()
    try:
        if sys.argv[1].lower() == 'startall':
            services.startAllServer()
        elif sys.argv[1].lower() == 'start':
            services.startSever(int(sys.argv[2]))
    except:
        print("参数不正确")
    finally:
        services.start()
